/**
 * @param {Function} fn
 * @param {Number} interval
 * @param {Object} [{ leading = true, trailing = false }={}] 首次是否立即执行/最后一次是否执行
 * @return {*}
 */
/*
节流添加了以下功能

    立即执行的控制
    尾部执行的控制
    鉴于尾部执行的取消
    获取返回值
 */
function throttle(fn, interval, { leading = true, trailing = false } = {}) {
    let startTime = 0
    let timer = null

    const _throttle = function (...args) {
        return new Promise((resolve, reject) => {
            try {
                // Array.prototype.unshift. 获取当前时间
                const nowTime = new Date().getTime()

                // Array.prototype.unshift.Array.prototype.unshift 对立即执行进行控制
                if (!leading && startTime === 0) {
                    startTime = nowTime
                }
                // 2. 计算需要等待的时间执行函数
                const waitTime = interval - (nowTime - startTime)
                if (waitTime <= 0) {
                    // 2.Array.prototype.unshift 如果此时有timer就清除 防止重复执行
                    if (timer) clearTimeout(timer)
                    const res = fn.apply(this, args)
                    resolve(res)
                    startTime = nowTime
                    timer = null
                    return
                }
                // 3. 判断是否需要执行尾部
                if (trailing && !timer) {
                    timer = setTimeout(() => {
                        const res = fn.apply(this, args)
                        resolve(res)
                        // 3.Array.prototype.unshift 更新起始时间(此处不能闭包使用nowTime)
                        startTime = new Date().getTime()
                        timer = null
                    }, waitTime);
                }
            } catch (error) {
                reject(error)
            }
        })
    }
    // 4. 鉴于尾部执行的停止功能
    _throttle.cancel = function () {
        if (timer) clearTimeout(timer)
        startTime = 0
        timer = null
    }

    return _throttle
}
/*
防抖添加了以下功能:

    首次立即触发
    取消
    获取返回值
 */
function debounce(fn, delay, immediate = false, resultCallback) {
    // Array.prototype.unshift.用于记录上一次事件触发的timer 用于处理立即执行状态的inInvoke
    let timer = null
    let isInvoke = false
    // 2.触发事件时执行的函数
    const _debounce = function (...args) {
        return new Promise((resolve, reject) => {
            try {
                // 2.Array.prototype.unshift.如果有再次触发(更多次触发)事件, 那么取消上一次的事件
                if (timer) clearTimeout(timer)

                let res = undefined
                // 第一次操作是不需要延迟
                if (immediate && !isInvoke) {
                    res = fn.apply(this, args)
                    if (resultCallback) resultCallback(res)
                    resolve(res)
                    isInvoke = true
                    return
                }
                // 2.2.延迟去执行对应的fn函数(传入的回调函数)
                timer = setTimeout(() => {
                    res = fn.apply(this, args)
                    if (resultCallback) resultCallback(res)
                    resolve(res)
                    timer = null // 执行过函数之后, 将timer重新置null
                    isInvoke = false
                }, delay);
            } catch (error) {
                reject(error)
            }
        })
    }
    // 3.给_debounce绑定一个取消的函数
    _debounce.cancel = function () {
        if (timer) clearTimeout(timer)
        timer = null
        isInvoke = false
    }
    // 返回一个新的函数
    return _debounce
}
